﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using System.Collections;
using System.ComponentModel;
using Microsoft.SharePoint.Taxonomy;

namespace SPSilver.Common
{
    public abstract class List
    {
        public virtual SPList list { get; protected set; }
        public void Update(Item i)
        {
            if (i.PropertiesHaveChanged)
            {
                SPListItem item = list.GetItemById(i.ID);
                foreach (DictionaryEntry property in i.AfterProperties)
                {
                    item[(Guid)property.Key] = property.Value;
                }
            }
        }
    }

    public partial class Item
    {
        public SPFieldCollection fieldsCol { get; private set; }
        public int ID { get; private set; }
        public Guid UniqueId { get; private set; }
        public String Title { get; private set; }
        public String Editor { get; private set; }
        public String Author { get; private set; }
        public DateTime Created { get; private set; }
        public DateTime Modified { get; private set; }
        public int Culture { get; set; }

        public Guid listID { get; private set; }
        public String webUrl { get; private set; }
        public enum CultureEnum { el = 1032, en };

        public Item(SPListItem i)
        {
            Culture = System.Globalization.CultureInfo.CurrentCulture.LCID;

            if (i.ListItems != null)
            {
                fieldsCol = i.ListItems.Fields;
            }
            else
            {
                fieldsCol = null;
            }
            if (i.ID > 0)
            {
                ID = i.ID;
                UniqueId = i.UniqueId;
                try{Title = safe<String>(i, Fields.Title);}catch{};
                try{Editor = safe<SPFieldLookupValue>(i, Fields.Editor).LookupValue;}catch{Editor=String.Empty;};
                try{Author = safe<SPFieldLookupValue>(i, Fields.Author).LookupValue;}catch{Author = String.Empty;};
                try{Created = safe<DateTime>(i, Fields.Created);}catch{Created=DateTime.MinValue;};
                try{Modified = safe<DateTime>(i, Fields.Modified);}catch{Modified=DateTime.MinValue;};

                listID = i.ParentList.ID;
                webUrl = i.Web.Url;
            }
        }

        /// <summary>
        /// the url address of the display form of this item
        /// </summary>
        public string Url
        {
            get
            {
                StringBuilder link = new StringBuilder();
                link.Append(webUrl);
                if (webUrl.Substring(webUrl.Length - 1, 1) != "/")
                    link.Append("/");
                link.AppendFormat("_layouts/15/listform.aspx?PageType=4&ListId={0}&ID={1}&RootFolder=*", 
                    listID.ToString(), ID);
                return link.ToString();
            }
        }
        /// <summary>
        /// the anchor html code of this item
        /// </summary>
        /// <param name="hyperlinkText">the hyperlink text of this anchor</param>
        /// <returns></returns>
        public String anchorHtml(String hyperlinkText)
        {
            return String.Format("<a href=\"{0}\" onclick=\"javascript:openInDialog(900, 600, true, true, false, '{0}');return (false);\">{1}</a>",
                                        this.Url, hyperlinkText);
        }

        /// <summary>
        /// the anchor html code of this item using the title as hyperlink text
        /// </summary>
        /// <returns></returns>
        public String anchorHtml()
        {
            return String.Format("<a href=\"{0}\" onclick=\"javascript:openInDialog(900, 600, true, true, false, '{0}');return (false);\">{1}</a>",
                                        this.Url, this.Title);
        }

        public List<DictionaryEntry> AfterProperties = new List<DictionaryEntry>();
	
        private bool _propertiesHaveChanged;
        public bool PropertiesHaveChanged
        {
            get { return _propertiesHaveChanged; }
            private set { _propertiesHaveChanged = value; }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName, Guid propertyGuid, object propertyValue)
        {
            _propertiesHaveChanged = true;
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
            AfterProperties.Add(new DictionaryEntry(propertyGuid, propertyValue.ToString()));
        }

        protected virtual void OnPropertyChanged(string propertyName, object propertyValue)
        {
            _propertiesHaveChanged = true;
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
            AfterProperties.Add(new DictionaryEntry(propertyName, propertyValue.ToString()));
        }

        protected T safe<T>(SPListItem item, string fieldName)
        {
            if (item[fieldName] != null)
            {
                switch (typeof(T).Name)
                {
                    case "String":
                    case "SPFieldFile":
                    case "SPFieldComputed":
                        return (T)Convert.ChangeType(safeString(item, fieldName), typeof(T));
                    case "SPFieldLookupValue":
                        return (T)Convert.ChangeType(safeSPFieldLookupValue(item, fieldName), typeof(T));
                    case "SPFieldLookupValueCollection":
                        return (T)Convert.ChangeType(safeSPFieldLookupValueCollection(item, fieldName), typeof(T));
                    case "Int32":
                    case "Int16":
                    case "int":
                        return (T)Convert.ChangeType(safeInt32(item, fieldName), typeof(T));
                    case "Microsoft.SharePoint.SPFieldUrlValue":
                    case "SPFieldUrlValue":
                        return (T)Convert.ChangeType(new SPFieldUrlValue(safeString(item, fieldName)), typeof(T));
                    case "SPFieldUserValue":
                        return (T)Convert.ChangeType(new SPFieldUserValue(item.Web, safeString(item, fieldName)), typeof(T));
                    case "TaxonomyFieldValue":
                        return (T)Convert.ChangeType((TaxonomyFieldValue)item[fieldName], typeof(T));
                    case "TaxonomyFieldValueCollection":
                        return (T)Convert.ChangeType((TaxonomyFieldValueCollection)item[fieldName], typeof(T));
                    case "SPFieldMultiChoiceValue":
                        {
                            var fields = item.Fields;
                            SPFieldMultiChoice choiceField = fields.GetFieldByInternalName(fieldName) as SPFieldMultiChoice;
                            var val = item[choiceField.Title].ToString();
                            return (T)choiceField.GetFieldValue(val);
                        }
                    case "SPFieldChoiceValue":
                        {
                            var fields = item.Fields;
                            SPFieldChoice choiceField = fields.GetFieldByInternalName(fieldName) as SPFieldChoice;
                            var val = item[choiceField.Title].ToString();
                            return (T)choiceField.GetFieldValue(val);
                        }
                    default:
                        return (T)item[fieldName];
                }
            }
            return default(T);
        }
        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν string</returns>
        private string safeString(object p)
        {
            if (p == null)
                return String.Empty;
            else
                return p.ToString();
        }

        private string safeString(SPListItem item, string fieldName)
        {
            string toReturn = String.Empty;
            try
            {
                if ((fieldsCol == null) || (fieldsCol.ContainsField(fieldName)))
                {
                        if (item[fieldName] != null)
                            toReturn = item[fieldName].ToString();
                }
            }
            catch { }
            return toReturn;
        }


        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν SPFieldLookupValueCollection</returns>
        private SPFieldLookupValueCollection safeSPFieldLookupValueCollection(object p)
        {
            SPFieldLookupValueCollection coll = new SPFieldLookupValueCollection();
            if (p == null)
            {
                return coll;
            }
            else
            {
                try
                {
                    coll.AddRange(new SPFieldLookupValueCollection(p.ToString()));
                }
                catch//  (Exception e)
                { }
                return coll;
            }
        }

        private SPFieldLookupValueCollection safeSPFieldLookupValueCollection(SPListItem item, string fieldName)
        {
            SPFieldLookupValueCollection result = new SPFieldLookupValueCollection();
            if ((fieldsCol == null) || (fieldsCol.ContainsField(fieldName)))
            {
                try
                {
                    if (item[fieldName] != null)
                        result.AddRange(new SPFieldLookupValueCollection(item[fieldName].ToString()));
                }
                catch { }
            }
            return result;
        }


        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν SPFieldLookupValue</returns>
        private SPFieldLookupValue safeSPFieldLookupValue(object p)
        {
            SPFieldLookupValue coll = new SPFieldLookupValue(0, String.Empty);
            if (p == null)
            {
                return coll;
            }
            else
            {
                try
                {
                    coll = new SPFieldLookupValue(p.ToString());
                }
                catch// (Exception e)
                { }
                return coll;
            }
        }

        private SPFieldLookupValue safeSPFieldLookupValue(SPListItem item, string fieldName)
        {
            SPFieldLookupValue result = new SPFieldLookupValue(0, String.Empty);
            try
            {
                if ((fieldsCol == null) || (fieldsCol.ContainsField(fieldName)))
                {
                        if (item[fieldName] != null)
                            result = new SPFieldLookupValue(item[fieldName].ToString());
                }
            }
            catch { }
            return result;
        }


        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν SPFieldLookupValue</returns>
        private DateTime safeDateTime(object p)
        {
            DateTime dt = DateTime.MinValue;
            if (p == null)
            {
                return dt;
            }
            else
            {
                try
                {
                    if (DateTime.TryParse(p.ToString(), out dt))
                        return dt;
                }
                catch//  (Exception e)
                { }
                return dt;
            }
        }

        private DateTime safeDateTime(SPListItem item, string fieldName)
        {
            DateTime result = DateTime.MinValue;
            if ((fieldsCol == null) || (fieldsCol.ContainsField(fieldName)))
            {
                try
                {
                    if (item[fieldName] != null)
                        DateTime.TryParse(item[fieldName].ToString(), out result);
                }
                catch { }
            }
            return result;
        }

        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν Boolean</returns>
        private Boolean safeBoolean(object p)
        {
            Boolean result = false;
            if (p != null)
                Boolean.TryParse(p.ToString(), out result);
            return result;
        }


        private Boolean safeBoolean(SPListItem item, string fieldName)
        {
            Boolean result = false;
            if ((fieldsCol == null) || (fieldsCol.ContainsField(fieldName)))
            {
                try
                {
                    if (item[fieldName] != null)
                        Boolean.TryParse(item[fieldName].ToString(), out result);
                }
                catch { }
            }
            return result;
        }


        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν string</returns>
        /*public string safeLink(object p)
        {
            if (p == null)
                return String.Empty;
            else
            {
                String link = String.Empty;
                try
                {
                    String[] arr = new String[2] { String.Empty, String.Empty };
                    String temp = safeString(p);
                    arr = temp.Split(new char[] { ',' });
                    link = String.Format("<a href=\"{0}\" title=\"{1}\">{1}</a>", arr[0], arr[1]);
                }
                catch// (Exception e) 
                { }
                return link;
            }
        }*/
        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν Int32</returns>
        /*public Int32 safeInt(SPListItem i, string fieldName)
        {
            Int32 result = 0;
            if (i!=null)
            {
                bool contains = false;
                using (SPMonitoredScope mon2 = new SPMonitoredScope("throws i.ListItems.Fields.ContainsField(fieldName)"))
                {
                    try
                    {
                        object p = i[fieldName+"-"];
                        if (p != null)
                            Int32.TryParse(p.ToString(), out result);
                    }
                    catch { }
                }
                using (SPMonitoredScope mon = new SPMonitoredScope("fake i.ListItems"))
                {
                    SPListItemCollection coll = i.ListItems;
                    // using (SPMonitoredScope mon1 = new SPMonitoredScope("fake i.ListItems.Fields"))
                    {
                        SPFieldCollection fcoll = coll.Fields;
                        // using (SPMonitoredScope mon2 = new SPMonitoredScope("fake i.ListItems.Fields.ContainsField(fieldName)"))
                        {
                            contains = fcoll.ContainsField(fieldName + "-");
                        }
                    }
                }
                using (SPMonitoredScope mon = new SPMonitoredScope("i.ListItems"))
                {
                    SPListItemCollection coll = i.ListItems;
                    // using (SPMonitoredScope mon1 = new SPMonitoredScope("i.ListItems.Fields"))
                    {
                        SPFieldCollection fcoll = coll.Fields;
                        // using (SPMonitoredScope mon2 = new SPMonitoredScope("i.ListItems.Fields.ContainsField(fieldName)"))
                        {
                            contains = fcoll.ContainsField(fieldName);
                        }
                    }
                }
                if (!contains)
                {
                    return result;
                }
                else
                {
                    try
                    {
                        object p = i[fieldName];
                        if (p != null)
                        Int32.TryParse(p.ToString(), out result);
                    }catch{}
                }
            }
            return result;
        }*/


        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν string</returns>
        /*public string safeLinkOnly(object p)
        {
            if (p == null)
                return String.Empty;
            else
            {
                String link = String.Empty;
                try
                {
                    String[] arr = new String[2] { String.Empty, String.Empty };
                    String temp = safeString(p);
                    arr = temp.Split(new char[] { ',' });
                    link = arr[0];
                }
                catch // (Exception e) 
                { }
                return link;
            }
        }*/


        private string safeLinkOnly(SPListItem item, string fieldName)
        {
            string result = String.Empty;
            if ((fieldsCol == null) || (fieldsCol.ContainsField(fieldName)))
            {
                try
                {
                    if (item[fieldName] != null)
                    {
                        String[] arr = new String[2] { String.Empty, String.Empty };
                        String temp = safeString(item, fieldName);
                        arr = temp.Split(new char[] { ',' });
                        result = arr[0];
                    }
                }
                catch { }
            }
            return result;
        }


        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν string</returns>
        /*internal string safeLinkOnly(object p)
        {
            if (p == null)
                return String.Empty;
            else
            {
                String link = String.Empty;
                try
                {
                    String[] arr = new String[2] { String.Empty, String.Empty };
                    String temp = safeString(p);
                    arr = temp.Split(new char[] { ',' });
                    link = arr[0];
                }
                catch (Exception e) { }
                return link;
            }
        }
        */
        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν Int32</returns>
        private Int32 safeInt32(object p)
        {
            return safeInt(p);
        }

        /// <summary> Επιστρέφει μια ασφαλή τιμή</summary>
        /// <param name="p">την τιμή ενός πεδίου</param>
        /// <returns>την τιμή σαν Int32</returns>
        private Int32 safeInt(object p)
        {
            Int32 result = 0;
            if (p != null)
                Int32.TryParse(p.ToString(), out result);
            return result;
        }
        private Int32 safeInt32(SPListItem item, string fieldName)
        { 
            return safeInt(item, fieldName);
        }

        private Int32 safeInt(SPListItem item, string fieldName)
        {
            Int32 result = 0;
            if ((fieldsCol == null) || (fieldsCol.ContainsField(fieldName)))
            {
                try
                {
                    if (item[fieldName] != null)
                        Int32.TryParse(item[fieldName].ToString(), out result);
                }
                catch { }
            }
            return result;
        }


        public class Fields
        {
            public static readonly String Editor = "Editor";
            public static readonly String Author = "Author";
            public static readonly String Created = "Created";
            public static readonly String Modified = "Modified";
            public static readonly String Title = "Title";
        }
    }
}
